from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from loguru import logger

from database import models
from tg_bot.filters.user_filter import IsActive
from tg_bot.keyboards import inline, callback_factory as cf
from tg_bot.states.user import PersonalAccount

router = Router()
router.message.filter(IsActive())
router.callback_query.filter(IsActive())


@router.callback_query(cf.ActionCall.filter(
    F.action == 'balance_history'
), PersonalAccount.main)
async def balance_history(call: types.CallbackQuery,
                          state: FSMContext,
                          user: models.TgUser):
    """
    История баланса пользователя по инлайн кнопке.

    ----
    :param call: Callback.
    :param state: State.
    :param user: Пользователь.
    :return:
    """
    logs = user.logs.filter(change_type=models.LogTgUser.ChangeType.BALANCE).order_by('-date_create')
    if logs.count() == 0:
        await call.answer('У вас нет истории баланса!', show_alert=True)
    else:
        await state.set_state(PersonalAccount.balance_history)
        await user_balance_log_message(call.message, state, logs)


async def user_balance_log_message(
        message: types.Message,
        state: FSMContext,
        logs: models.CustomQuerySet[models.LogTgUser]
):
    """
    Вывод информации по истории баланса пользователя.

    ----
    :param message: Сообщение тг.
    :param state: Состояние пользователя.
    :param logs: Логи пользователя.
    :return:
    """
    data = await state.get_data()
    balance_page: int = data.get('balance_page', 1)
    pages = await inline.get_pages_count(logs.count(), 20)
    start, stop = await inline.get_start_stop_slice(balance_page, 20)
    text = 'История изменения баланса: \n'
    prev_date = ''
    for log in logs[start:stop]:
        new_date = log.date_create.strftime("%d.%m.%Y")
        if new_date != prev_date:
            text += f'\n{new_date}\n'
            prev_date = new_date
        balance_value = round((float(log.changed_to) - float(log.changed_from)),
                              2)
        text += f'{log.comment} '
        text += f'(+{balance_value})\n' if balance_value > 0 else f'({balance_value})\n'
    key = await inline.concatenate_key(
        await inline.pagination(balance_page, pages),
        await inline.back('personal_account')
    )
    try:
        await message.edit_text(text, reply_markup=key)
    except Exception as e:
        logger.warning(e)
        await message.answer(text, reply_markup=key)


@router.callback_query(cf.AdminActionCall.filter(
    F.action.in_({'next_page', 'prev_page'})
), PersonalAccount.balance_history)
async def user_balance_history_pagination(call: types.CallbackQuery,
                                          state: FSMContext,
                                          callback_data: cf.AdminActionCall,
                                          user: models.TgUser):
    """
    Пагинация истории баланса пользователя.

    ----
    :param call: Callback.
    :param state: State.
    :param callback_data: Callback data для пагинации.
    :param user: Пользователь.
    :return:
    """
    logs = user.logs.filter(change_type=models.LogTgUser.ChangeType.BALANCE).order_by('-date_create')
    data = await state.get_data()
    balance_page: int = data.get('balance_page', 1)
    balance_page += 1 if callback_data.action == 'next_page' else -1
    await state.update_data({'balance_page': balance_page})
    await user_balance_log_message(call.message, state, logs)

